package com.hccl.server;

import com.hccl.mongoEntities.*;
import org.bson.types.ObjectId;
import org.mongodb.morphia.Datastore;
import com.hccl.config.MongoDB;
import org.mongodb.morphia.query.Query;

import java.io.*;
import java.util.*;

import static com.hccl.mongoEntities.StateMachineModelEntity.getModelFromInternelJson;

public class Import
{
    private static Datastore mongoDatastore;
    private static String mongodbIp;
    private static String mongodbPort;
    private static String databaseName;

    private static void init(){

        Properties property=new Properties();
        try {
            property.load(new FileInputStream("lib/config.inf"));
            mongodbIp = property.getProperty("mongodbIp","localhost");
            mongodbPort = property.getProperty("mongodbPort","27017");
            databaseName = property.getProperty("databaseName","nxyd4");
        } catch (Exception e) {
            System.err.println("Loading configuration failed, please check. Using default parameters.");
            System.exit(-1);
        }
        MongoDB.setDBConf(databaseName, mongodbIp, "", "", Integer.valueOf(mongodbPort));
        mongoDatastore= MongoDB.instance().getDatabase();
    }

    private static void updateDB(String[] args) {
//        if (args.length!=3) {
//            System.out.println("usage: 模型json文件 节点语料所在文件夹 全局命令所在文件夹");
//            return;
//        }
//        if(mongoDatastore.createQuery(NavigationEntity.class).countAll()>0) {
//            System.out.println("连接数据库成功");
//        }
        mongoDatastore.delete(mongoDatastore.createQuery(NavigationEntity.class));
        mongoDatastore.delete(mongoDatastore.createQuery(ProcessEntity.class));
        mongoDatastore.delete(mongoDatastore.createQuery(APIsEntity.class));
        mongoDatastore.delete(mongoDatastore.createQuery(ConfigEntity.class));
        mongoDatastore.delete(mongoDatastore.createQuery(GrammarVariableEntity.class));
        mongoDatastore.delete(mongoDatastore.createQuery(GrammarSlotEntity.class));
        mongoDatastore.delete(mongoDatastore.createQuery(GrammarRuleEntity.class));
        mongoDatastore.delete(mongoDatastore.createQuery(GrammarElementEntity.class));
        mongoDatastore.delete(mongoDatastore.createQuery(CommandEntity.class));

        try{
            createMenufromModel(args[0]); //从Json获取menu、vari、process、config、APIs，并存入数据库
            createRule(args[2], args[1]); //rule、slot入库
            creatVirtualNode();           //虚拟节点，每个变量对应着一条语法
            createCorpus(args[3]);       //node语料存到数据库
            creatGramEle(args[1]);       //语义要素存入数据库
            createCommands(args[4],args[5], args[1]);//存command的语料和语法

        } catch (Exception e){
            System.out.println(e);
        }
        if(mongoDatastore.createQuery(NavigationEntity.class).countAll()>0){
            System.out.println("更新成功");
        }
    }

    private static void createMenufromModel(String path) {

        StateMachineModelEntity model = getModelFromInternelJson(path, StateMachineModelEntity.class);

        //vari入库
        List<GrammarVariableEntity> paramLs= model.getParams();
        for (GrammarVariableEntity p : paramLs){
            mongoDatastore.save(p);
        }

        //menu入库
        NavigationEntity rootNode =  model.getRoot();
        if(rootNode != null){
            createMenu(null,rootNode);
        }

        //process入库
        List<ProcessEntity> processLs = model.getProcesses();
        for (ProcessEntity p : processLs){
            mongoDatastore.save(p);
        }

        //config入库
        ConfigEntity config = model.getConfig();
        mongoDatastore.save(config);

        //APIs入库
        List<APIsEntity> apiList = model.getApis();
        for (APIsEntity api : apiList){
            mongoDatastore.save(api);
        }

    }

    private static void createMenu(NavigationEntity parent, NavigationEntity curNavi){

        NavigationEntity menuTmp = mongoDatastore.createQuery(NavigationEntity.class)
                .field("id").equal(curNavi.getId()).get();
        if (menuTmp == null) {
            curNavi.setParent(parent);
            mongoDatastore.save(curNavi);
        }
        if(curNavi.getSubStateNode()!=null){
            List<? extends NavigationEntity> cl = curNavi.getSubStateNode();
            for (NavigationEntity cnavi:cl){
                createMenu(curNavi, cnavi);
            }
        }

    }

    //语义槽、语法存到数据库,边读jape文件边存
    private static void createRule(String filename,String path) throws IOException {

        File file = new File(filename);
        if (file.exists()) {
            Map<String, GrammarSlotEntity> slotMap = new HashMap<String, GrammarSlotEntity>();
            Map<String, GrammarVariableEntity> variMap = new HashMap<String, GrammarVariableEntity>();//变量
            BufferedReader input = null;
            try {
                InputStreamReader isr = new InputStreamReader(new FileInputStream(new File(filename)), "UTF-8");
                input = new BufferedReader(isr);
                String line = "";
                NavigationEntity menu = null;
                List<GrammarRuleEntity> grammars = new ArrayList<GrammarRuleEntity>();
                while ((line = input.readLine()) != null) {
                    if (line.trim().equals(""))
                        continue;
                    if (line.endsWith(":") || line.endsWith("：")) {
                        if (menu != null) {
                            menu.setRules(grammars);
                            mongoDatastore.save(menu);
                        }
                        line = line.substring(0, line.length() - 1);
                        menu = mongoDatastore.createQuery(NavigationEntity.class).field("id").equal(line).get();//line=节点名
                        if (menu != null) grammars = menu.getRules();
                    } else {
                        GrammarRuleEntity rule = new GrammarRuleEntity();
                        rule.setOrdered(line.contains("#"));//有序语法
                        line = line.replace("#", "");
                        List<RuleEntryEntity> entries = new ArrayList<RuleEntryEntity>();//存放组成rule的元素：语义槽或者语义要素
                        String[] tokens = line.split(" ");
                        for (String token : tokens) {
                            boolean dispensable = false;
                            if (token.startsWith("[") && token.endsWith("]")) {
                                token = token.substring(1, token.length() - 1);
                                dispensable = true;
                            }
                            if (token.contains("$")) {//变量
                                String tokenTmp = token.replace("$", "");
                                GrammarVariableEntity vari = mongoDatastore.createQuery(GrammarVariableEntity.class).field("name").
                                        equal(tokenTmp).get();
                                if (vari == null) {
                                    break;
                                }
                                RuleEntryEntity entry_v = new RuleEntryEntity(vari.getName(), dispensable, 1);
                                entry_v.setName(token);
                                entries.add(entry_v);
                            } else {//语义槽
                                GrammarSlotEntity slot = slotMap.get(token);
                                if (slot == null) {
                                    try {
                                        slot = createSlotCN(path, token);//存语义槽到数据库
                                        slotMap.put(token, slot);
                                    } catch (IOException ex) {
                                        ex.printStackTrace();
                                        System.exit(-1);
                                    }
                                }
                                if (slot == null) {
                                    break;
                                } else {
                                    RuleEntryEntity entry_s = new RuleEntryEntity(slot.getId(), dispensable, 0);
                                    entry_s.setName(token);
                                    entries.add(entry_s);
                                }
                            }
                        }
                        rule.setLists(entries);
                        mongoDatastore.save(rule);
                        grammars.add(rule);
                    }
                }
                if (menu != null) {
                    menu.setRules(grammars);
                    mongoDatastore.save(menu);
                }
            } catch (FileNotFoundException ex) {
                ex.printStackTrace();
            } catch (IOException ex) {
                ex.printStackTrace();
            } finally {
                try {
                    if (input != null) {
                        input.close();
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

    private static GrammarSlotEntity createSlotCN(String path,String slotName) throws IOException {

        List<String> gazs = new ArrayList<String>();
        InputStreamReader isr = new InputStreamReader(new FileInputStream(new File(path+slotName+".lst")), "utf-8");
        BufferedReader readLst = new BufferedReader(isr);
        String gaz;
        while ((gaz = readLst.readLine()) != null) {
            if(gaz.trim().equals(""))
                continue;
            gazs.add(gaz);
        }
        if (readLst != null) {
            readLst.close();
        }
        GrammarSlotEntity slot  = new GrammarSlotEntity();
        if(!gazs.isEmpty()){
            slot.setId(slotName);
            slot.setLists(gazs);
            mongoDatastore.save(slot);
        }else {
            throw new IOException("slot " + slotName +" is empty");
        }
        return slot;
    }

    private static void creatVirtualNode() throws IOException {

        //生成一个名为“##”的节点,里面含有变量的语法，并存到数据库
        NavigationEntity tmpMenu = new NavigationEntity();
        tmpMenu.setId("##");
        List<GrammarRuleEntity> gram = new ArrayList<GrammarRuleEntity>();
        Query<GrammarVariableEntity>  varils = MongoDB.instance().getDatabase().createQuery(GrammarVariableEntity.class);
        for(GrammarVariableEntity v : varils){
            if(v.getType().equals(""))
                continue;
            GrammarRuleEntity rule = new GrammarRuleEntity();
            List<RuleEntryEntity> entries = new ArrayList<RuleEntryEntity>();
            RuleEntryEntity en_v = new RuleEntryEntity(v.getName(), false, 1);
            en_v.setName(v.getName());
            entries.add(en_v);
            rule.setLists(entries);
            mongoDatastore.save(rule);
            gram.add(rule);
        }

        tmpMenu.setRules(gram);
        mongoDatastore.save(tmpMenu);
    }

    private static void createCorpus(String corpusPath) throws IOException {

        File file = new File(corpusPath);
        if(file.exists()) {
            File[] files = file.listFiles();
            for (File oneFile : files) {
                String name = oneFile.getName();
                name = name.replace(".txt", "");
                InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(oneFile), "utf-8");
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                List<String> corpusLs = new ArrayList<String>();
                String line = "";
                while ((line = bufferedReader.readLine()) != null) {
                    line = line.toLowerCase();
                    if (line.trim().length() > 0) corpusLs.add(line);
                }
                bufferedReader.close();
                NavigationEntity menu = mongoDatastore.createQuery(NavigationEntity.class).field("id").equal(name).get();
                if (menu != null) {
                    menu.setCorpus(corpusLs);
                    mongoDatastore.save(menu);
                }
            }
        }
    }

    //有个隐患是必须需要commandcorpus，语法文件
    private  static void createCommands(String commandCorpusPath,
                                        String commandJapePath,
                                        String lstFilePath
    ) throws IOException {

        //存语料
        File file = new File(commandCorpusPath);
        if (file.exists()) {
            File[] files = file.listFiles();
            for (File oneFile : files) {
                String name = oneFile.getName();
                name = name.replace(".txt", "");
                InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(oneFile), "utf-8");
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                List<String> corpusLs = new ArrayList<String>();
                String line = "";
                while ((line = bufferedReader.readLine()) != null) {
                    line = line.toLowerCase();
                    if (line.trim().length() > 0) corpusLs.add(line);
                }
                CommandEntity command = new CommandEntity();
                command.setName(name);
                command.setOrdered(false);
                command.setCorpus(corpusLs);
                mongoDatastore.save(command);
            }
        }
        //存语法
        File fileJape = new File(commandJapePath);
        if (fileJape.exists()){
            Map<String, GrammarSlotEntity> slotMap = new HashMap<String, GrammarSlotEntity>();
            InputStreamReader read = new InputStreamReader(new FileInputStream(commandJapePath), "UTF-8");
            BufferedReader reader = new BufferedReader(read);
            String line = "";
            String name = "";
            List<GrammarRuleEntity> rules = new ArrayList<GrammarRuleEntity>();
            while ((line = reader.readLine()) != null) {
                if (line.trim().equals(""))
                    continue;
                if (line.endsWith(":") || line.endsWith("：")) {
                    if (rules.size() > 0) {
                        CommandEntity command = mongoDatastore.createQuery(CommandEntity.class).field("name")
                                .equal(name).get();
                        if (command==null) command = new CommandEntity();
                        command.setRules(rules);
                        command.setName(name);
                        mongoDatastore.save(command);
                    }
                    name = line.trim().replace(":", "").replace("：", "");
                    rules = new ArrayList<GrammarRuleEntity>();
                } else {
                    GrammarRuleEntity grammarRuleEntity = new GrammarRuleEntity();
                    List<RuleEntryEntity> entries = new ArrayList<RuleEntryEntity>();//存放组成rule的元素：语义槽
                    String[] tokens = line.split(" ");
                    for (String token : tokens) {
                        boolean dispensable = false;
                        if (token.startsWith("[") && token.endsWith("]")) {
                            token = token.substring(1, token.length() - 1);
                            dispensable = true;
                        }
                        GrammarSlotEntity slot = slotMap.get(token);
                        if (slot == null) {
                            try {
                                slot = createSlotCN(lstFilePath, token);//存语义槽到数据库
                                slotMap.put(token, slot);
                            } catch (IOException ex) {
                                ex.printStackTrace();
                                System.exit(-1);
                            }
                        }
                        if (slot == null) {
                            break;
                        } else {
                            RuleEntryEntity entry_s = new RuleEntryEntity(slot.getId(), dispensable, 0);
                            entry_s.setName(token);
                            entries.add(entry_s);
                        }
                    }
                    grammarRuleEntity.setId(new ObjectId());
                    grammarRuleEntity.setLists(entries);
                    mongoDatastore.save(grammarRuleEntity);
                    rules.add(grammarRuleEntity);
                }
            }
            //存最后一个command
            CommandEntity command = mongoDatastore.createQuery(CommandEntity.class).field("name")
                    .equal(name).get();
            if (command==null) command = new CommandEntity();
            command.setRules(rules);
            command.setName(name);
            mongoDatastore.save(command);
        }
    }

    private static void creatGramEle(String path)  {

        try {
            File[] entries =  new File(path).listFiles();
            for (int index=0; index<entries.length; index++) {
                if (entries[index].getName().contains(".csv")) {
                    GrammarElementEntity gramEle = new GrammarElementEntity();
                    List<EmbedElementEntity> eleLs= new ArrayList<EmbedElementEntity>();//存放语义要素里面的每一行
                    Set<String> attnameSet = new HashSet<String>();//存放属性名

                    InputStreamReader read = new InputStreamReader(new FileInputStream(entries[index]), "UTF-8");
                    BufferedReader reader = new BufferedReader(read);
                    String line = "";
                    line = reader.readLine();
                    if (line.split(",").length > 2) {//含属性列
                        String[] subAttKey = line.split(",")[1].split(";");//获取属性
                        while ((line = reader.readLine()) != null) {
                            EmbedElementEntity embedEle = new EmbedElementEntity();
                            String[] tokens = line.split(",");
                            //抽取名
                            embedEle.setStandardName(tokens[0]);
                            //属性
                            Map<String,String> attMap = new HashMap<String, String>();
                            String[] subAttValue = tokens[1].split(";");
                            for (int i=0; i<subAttValue.length; i++) {
                                attMap.put(subAttKey[i], subAttValue[i]);
                                attnameSet.add(subAttKey[i]);
                            }
                            embedEle.setAttlists(attMap);
                            //用户说法
                            embedEle.setUserinput(Arrays.asList(tokens[2].split(";")));//String[]转list<string>
                            eleLs.add(embedEle);
                        }
                    }else{//“货车轴数.csv”“车型分类.csv”不含属性列
                        while ((line = reader.readLine()) != null) {
                            EmbedElementEntity embedEle = new EmbedElementEntity();
                            String[] tokens = line.split(",");
                            //抽取名
                            embedEle.setStandardName(tokens[0]);
                            //用户说法
                            embedEle.setUserinput(Arrays.asList(tokens[1].split(";")));//String[]转list<string>
                            eleLs.add(embedEle);
                        }
                    }
                    gramEle.setElelists(eleLs);
                    gramEle.setName(entries[index].getName().replace(".csv",""));//文件名=语义要素名
                    gramEle.setAttnames(attnameSet);
                    mongoDatastore.save(gramEle);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static void main( String[] args ) {
        init();
        updateDB(args);
    }
}
